package com.cy.mall.service.fujue.impl;

import com.cy.mall.comm.constant.Constants;
import com.cy.mall.comm.utils.CommonUtils;
import com.cy.mall.comm.utils.JsonObjectMapper;
import com.cy.mall.comm.utils.RSAUtils;
import com.cy.mall.comm.utils.SHA256Utils;
import com.cy.mall.model.Result;
import com.cy.mall.model.dto.fujue.req.AddAttachmentParamDTO;
import com.cy.mall.model.dto.fujue.req.AdmittanceAndGetCreditsParamDTO;
import com.cy.mall.model.dto.fujue.req.GetH5AddressParamDTO;
import com.cy.mall.model.dto.fujue.req.GetH5UrlParamDTO;
import com.cy.mall.service.BaseService;
import com.cy.mall.service.fujue.FujueApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Description 对接富爵Api接口
 * @Author tanyilin
 * @Date 2019/3/25 11:05
 */
@Slf4j
@Service
public class FujueApiServiceImpl extends BaseService implements FujueApiService {

    @Autowired
    private RestTemplate restTemplate;

    private static String usedId = "3";
    @Value("${fujue.chnl-code}")
    private String fjChnlCode;
    @Value("${fujue.key}")
    private String fjKey;

    @Value("${fujue.get-h5-address-url}")
    private String getH5AddressRequestUrl;
    @Value("${fujue.query-loan-apply-data-url}")
    private String queryLoanApplyDataRequestUrl;
    @Value("${fujue.query-loan-data-url}")
    private String queryLoanDataRequestUrl;

    @Value("${fujue.jyd-base-request-url}")
    private String jydBaseRequestUrl;
    @Value("${fujue.chnl-code2}")
    private String fjChnlCode2;
    @Value("${fujue.jyd-prod-code}")
    private String prodCode;


    @Override
    public Result<Map<String, Object>> getH5Address(GetH5AddressParamDTO paramDTO) {

        //时间戳
        String timestamp = String.valueOf(System.currentTimeMillis());

        //签名参数，使用 LinkedHashMap 保证输出顺序按照添加顺序一致
        LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("fjChnlCode", fjChnlCode);
        linkedHashMap.put("productType", paramDTO.getProductType());
        linkedHashMap.put("mobileNo", paramDTO.getMobileNo());
        linkedHashMap.put("applyMoney", paramDTO.getApplyMoney());
        linkedHashMap.put("applyTerms", paramDTO.getApplyTerms());
        linkedHashMap.put("usedId", usedId);
        linkedHashMap.put("timestamp", timestamp);
        linkedHashMap.put("userId", paramDTO.getUserId());
        linkedHashMap.put("key", fjKey);
        String signStr = CommonUtils.getParamStr(linkedHashMap);
        //进行 SHA-256 签名摘要算法
        String sign = SHA256Utils.getSha256Str(signStr);
        log.info("SHA-256 签名字符串：{}", signStr);
        log.info("SHA-256   签名结果：{}", sign);
        //参数
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("mobileNo", paramDTO.getMobileNo());
        dataMap.put("userId", paramDTO.getUserId());
        dataMap.put("applyMoney", paramDTO.getApplyMoney());
        dataMap.put("applyTerms", paramDTO.getApplyTerms());
        dataMap.put("usedId", usedId);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode);
        paramMap.put("productType", paramDTO.getProductType());
        paramMap.put("sign", sign);
        paramMap.put("timestamp", timestamp);
        paramMap.put("data", dataMap);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，获取富爵H5页面地址，请求 url = {}", getH5AddressRequestUrl);
        log.info("请求 [富爵] Api ，获取富爵H5页面地址，请求报文 = {}", requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(getH5AddressRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("请求 [富爵] Api ，获取富爵H5页面地址 , 请求失败");
        }

        log.info("请求 [富爵] Api ，获取富爵H5页面地址，回调报文 = {}", responseEntity.getBody());

        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);

        String rtCode = String.valueOf(body.get("rtCode"));
        if(!"0000".equals(rtCode)) {

            if("0003".equals(rtCode)) {
                //0003：存量客户
                return Result.fail("您在其他平台有正在处理的订单，暂时不能申请该产品");
            }
            if("0004".equals(rtCode)) {
                //0004：存在其它未完成的产品订单
                return Result.fail("您已有正在申请的订单，暂时不能申请该产品");
            }

            return Result.fail("请求失败，message=" + body.get("rtMsg"));
        }

        String h5Url = String.valueOf(body.get("h5Url"));
        try {
            h5Url = URLDecoder.decode(h5Url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("h5Url decode 解码异常", e);
        }
        body.put("url", h5Url);

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> queryLoanApplyData(String userId, String productType) {

        //参数
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("userId", userId);
        dataMap.put("productType", productType);
        String dataJson = JsonObjectMapper.toJson(dataMap);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode);
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，获取进件数据，请求 url = {}", queryLoanApplyDataRequestUrl);
        log.info("请求 [富爵] Api ，获取进件数据，请求报文 = {}", requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(queryLoanApplyDataRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("请求 [富爵] Api ，获取进件数据 , 请求失败");
        }

        log.info("请求 [富爵] Api ，获取进件数据，回调报文 = {}", responseEntity.getBody());

        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> queryLoanData(String loanId) {

        //参数
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("loanId", loanId);
        String dataJson = JsonObjectMapper.toJson(dataMap);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode);
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，获取贷款数据，请求 url = {}", queryLoanDataRequestUrl);
        log.info("请求 [富爵] Api ，获取贷款数据，请求报文 = {}", requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(queryLoanDataRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("请求 [富爵] Api ，获取贷款数据 , 请求失败");
        }

        log.info("请求 [富爵] Api ，获取贷款数据，回调报文 = {}", responseEntity.getBody());

        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> getH5Url(GetH5UrlParamDTO getH5UrlParamDTO) {

        //请求参数data
        String dataJson = JsonObjectMapper.toJson(getH5UrlParamDTO);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode2);
        paramMap.put("serviceCode", "getH5Url");
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，获取 [{}] H5页面，请求 url = {}", getH5UrlParamDTO.getH5Type(), jydBaseRequestUrl);
        log.info("请求 [富爵] Api ，获取 [{}] H5页面，请求报文 = {}", getH5UrlParamDTO.getH5Type(), requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(jydBaseRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("获取 [" + getH5UrlParamDTO.getH5Type() + "] H5页面 , 请求失败");
        }

        log.info("请求 [富爵] Api ，获取 [{}] H5页面，返回报文 = {}", getH5UrlParamDTO.getH5Type(), responseEntity.getBody());
        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);
        String errorCode = String.valueOf(body.get("errorCode"));
        if(!"0000".equals(errorCode)) {
            return Result.fail("获取 [" + getH5UrlParamDTO.getH5Type() + "] H5页面失败，原因=" + body.get("message"));
        }

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> queryAuthStatus(String idCard) {

        //参数
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("idCard", idCard);
        String dataJson = JsonObjectMapper.toJson(dataMap);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode2);
        paramMap.put("serviceCode", "authStatus");
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，查询客户[{}]是否实名认证，请求 url = {}", idCard, jydBaseRequestUrl);
        log.info("请求 [富爵] Api ，查询客户[{}]是否实名认证，请求报文 = {}", idCard, requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(jydBaseRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("查询客户 [" + idCard + "] 是否实名认证 , 请求失败");
        }
        log.info("请求 [富爵] Api ，查询客户[{}]是否实名认证，返回报文 = {}", idCard, responseEntity.getBody());
        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);
        String errorCode = String.valueOf(body.get("errorCode"));
        if(!"0000".equals(errorCode)) {
            return Result.fail("查询客户 [" + idCard + "] 是否实名认证失败，原因=" + body.get("message"));
        }

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> admittanceAndGetCredits(AdmittanceAndGetCreditsParamDTO paramDTO) {

        paramDTO.setProdCode(prodCode);
        paramDTO.setProdName("家具分期");
        //请求参数data
        String dataJson = JsonObjectMapper.toJson(paramDTO);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode2);
        paramMap.put("serviceCode", "admittanceAndGetCredits");
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，客户[{}]获取准入额度，请求 url = {}", paramDTO.getCustName(), jydBaseRequestUrl);
        log.info("请求 [富爵] Api ，客户[{}]获取准入额度，请求报文 = {}", paramDTO.getCustName(), requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(jydBaseRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("客户 [" + paramDTO.getCustName() + "] 获取准入额度，请求失败");
        }
        log.info("请求 [富爵] Api ，客户[{}]获取准入额度，返回报文 = {}", paramDTO.getCustName(), responseEntity.getBody());
        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);
        String errorCode = String.valueOf(body.get("errorCode"));
        if(!"0000".equals(errorCode)) {
            return Result.fail("客户 [" + paramDTO.getCustName() + "] 获取准入额度失败，原因=" + body.get("message"));
        }

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> getOrderInfo(String loanId) {

        //参数
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("loanId", loanId);
        String dataJson = JsonObjectMapper.toJson(dataMap);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode2);
        paramMap.put("serviceCode", "getOrderInfo");
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，获取订单[loanId={}]数据，请求 url = {}", loanId, jydBaseRequestUrl);
        log.info("请求 [富爵] Api ，获取订单[loanId={}]数据，请求报文 = {}", loanId, requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(jydBaseRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("获取订单 [loanId=" + loanId + "] 数据 , 请求失败");
        }
        log.info("请求 [富爵] Api ，获取订单[loanId={}]数据，返回报文 = {}", loanId, responseEntity.getBody());
        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);
        String errorCode = String.valueOf(body.get("errorCode"));
        if(!"0000".equals(errorCode)) {
            return Result.fail("获取订单 [loanId=" + loanId + "] 数据失败，原因=" + body.get("message"));
        }

        return Result.success("", body);
    }

    @Override
    public Result<Map<String, Object>> addAttachment(AddAttachmentParamDTO paramDTO) {

        //请求参数data
        String dataJson = JsonObjectMapper.toJson(paramDTO);
        //将json字符串对象进行 RSA 公钥加密
        String encodedData = RSAUtils.publicEncrypt(dataJson, Constants.FUJUE_RSA_PUBLIC_KEY);
        log.info("RSA 加密字符串，明文：{}", dataJson);
        log.info("RSA 加密字符串，密文：{}", encodedData);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fjChnlCode", fjChnlCode2);
        paramMap.put("serviceCode", "addAttachment");
        paramMap.put("data", encodedData);
        //最终请求的json数据
        String requestJson = JsonObjectMapper.toJson(paramMap);

        //设置 HttpHeaders、HttpEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<>(requestJson, headers);

        log.info("请求 [富爵] Api ，订单[loanId={}]补充资料，请求 url = {}", paramDTO.getLoanId(), jydBaseRequestUrl);
        log.info("请求 [富爵] Api ，订单[loanId={}]补充资料，请求报文 = {}", paramDTO.getLoanId(), requestJson);
        //发送post请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(jydBaseRequestUrl, HttpMethod.POST, httpEntity, String.class);

        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            return Result.fail("订单 [loanId=" + paramDTO.getLoanId() + "] 补充资料 , 请求失败");
        }
        log.info("请求 [富爵] Api ，订单[loanId={}]补充资料，返回报文 = {}", paramDTO.getLoanId(), responseEntity.getBody());

        Map<String, Object> body = JsonObjectMapper.read(responseEntity.getBody(), Map.class);
        String errorCode = String.valueOf(body.get("errorCode"));
        if(!"0000".equals(errorCode)) {
            return Result.fail("订单 [loanId=" + paramDTO.getLoanId() + "] 补充资料失败，原因=" + body.get("message"));
        }

        return Result.success("", body);
    }

    private String getErrorCodeDesc(String errorCode) {
        String errorCodeDesc = "";
        switch (errorCode) {
            case "0000":
                errorCodeDesc = "请求成功";
                break;
            case "0001":
                errorCodeDesc = "系统异常";
                break;
            case "0002":
                errorCodeDesc = "参数不全";
                break;
            case "0003":
                errorCodeDesc = "验签失败";
                break;
//            case "0004":
//                errorCodeDesc = "放款中";
//                break;
//            case "0005":
//                errorCodeDesc = "放款失败";
//                break;
//            case "0006":
//                errorCodeDesc = "放款成功";
//                break;
//            case "0007":
//                errorCodeDesc = "客户取消";
//                break;
//            case "0008":
//                errorCodeDesc = "订单号错误";
//                break;
            default:
                break;
        }
        return errorCodeDesc;
    }
}
